package servidor;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.ServerSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import requisicao.ObservadorRequisicao;
import requisicao.Requisicao;
import view.Legenda;
import contratos.Servidor;
import contratos.Ui;

public class MeuServidor implements Runnable, Observado, ObservadorRequisicao, Servidor {

	private int porta;
	private ServerSocket serverSocket = null;
	private boolean ativo;
	private List<ObservadorServidor> observadores = new ArrayList<ObservadorServidor>();
	private Ui ui;
	private boolean rodando = false;
	private Thread threadPrincipal;
	
	public MeuServidor(int porta){
		this.porta = porta;
	}
	
	@Override
	public void iniciar() {
		iniciarServerSocket();
		if(ativo){
			threadPrincipal = new Thread(this);
			threadPrincipal.start();
		}
	}
	
	@Override
	public void parar(){
		this.ativo = false;
	}

	@Override
	public void addObservador(Ui ui) {
		this.ui = ui;
		
	}
	
	@Override
	public void run() {
//		inicializar();
		rodando = true;
		atualizarLegenda();
		while(ativo){
			receberConexoes();
		}
		finalizarServerSocket();
		rodando = false;
		atualizarLegenda();
	}
	
	private void iniciarServerSocket() {	
		if(serverSocket!= null){
			finalizarServerSocket();
		}
		try {
			serverSocket = new ServerSocket(porta);							
//			notificarObservadores();
			ativo = true;
			ui.atualizarLog(true, "Server socket iniciado com sucesso!");
		} catch (IOException e) {
			ui.atualizarLog(false, e.getMessage());
		}finally{
			atualizarLegenda();		
		}
		
	}
	
	private void atualizarLegenda(){			
		Legenda legenda = new Legenda(ativo, getEstado(), getPorta(), getIp());
		ui.atualizarLegenda(legenda);
	}

	private String getEstado(){
		String estado = "offline";
		if(ativo && rodando){
			estado = "online";
		}else if(ativo && !rodando){
			estado = "aguarde";
		}
		return estado;
	}
	
	private String getIp(){
		String ip = "inicie o servidor";
		if(ativo && rodando){
			Inet4Address IP;
			try {
				IP = (Inet4Address) Inet4Address.getLocalHost();
				ip = IP.getHostAddress();
			} catch (UnknownHostException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else if(rodando && !rodando){
			ip = "aguarde";
		}
		
		return ip;
	}
	
	private String getPorta(){
		String porta = "inicie o servidor";
		if(ativo && rodando){
			porta =  ""+this.porta;
		}else if(ativo && !rodando){
			porta = "aguarde"; 
		}
		return porta;
	}
	
	private void finalizarServerSocket() {
		try {
			serverSocket.close();
			ui.atualizarLog(true, "Server socket encerrado");
		} catch (IOException e) {
			ui.atualizarLog(false, "Falha ao encerrar ServerSocket");
		}
//		notificarObservadores();
	}

	
	
	private void receberConexoes() {		
		try {
			serverSocket.setSoTimeout(100);
			Requisicao req = new Requisicao(serverSocket.accept(), ui);			
			new Thread(req).start();
			
		} catch (SocketException e) {	
		} catch (IOException e) {
			// TODO Auto-generated catch block
//			e.printStackTrace();
		}
	}
//
//	@Override
//	public void addObservador(ObservadorServidor observador) {
//		observadores.add(observador);		
//	}

	@Override
	public void remObservador(ObservadorServidor observador) {
		observadores.remove(observador);
		
	}

	@Override
	public void notificarObservadores() {
		for (ObservadorServidor observador : observadores) {
			observador.servidorAtualizado(this);
		}		
	}

//	public void setAtivo(boolean ativo){
//		this.ativo = ativo;
//	}
	
	

//	@Override
//	public int getPorta() {
//		return porta;
//	}
	@Override
	public void requisicaoAtualizada(Requisicao requisicao) {
		notificarObservadores();
	}

//	@Override
//	public String getIp() {
//		String ip = "Ip desconhecido";
//		try {
//			InetAddress IP = Inet4Address.getLocalHost();
//			ip = IP.getHostAddress();
//		} catch (UnknownHostException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		return ip;
//	}

	

	@Override
	public void addObservador(ObservadorServidor observador) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean isAtivo() {
		return ativo;
	}

	@Override
	public boolean isRodando() {
		return rodando;
	}

}
